/**
 * @file client_response.h
 * @brief 客户端响应结构定义文件
 * 
 * @details 该文件定义了交易所系统中客户端响应的结构和类型，
 * 包括客户端响应类型、匹配引擎内部使用的客户端响应结构和
 * 网络传输的客户端响应结构。这些结构用于交易所和客户端之间的通信。
 * 
 * @author 原作者
 * @date 2023
 */

#pragma once

#include <sstream>

#include "common/types.h"
#include "common/lf_queue.h"

using namespace Common;

namespace Exchange {
  /**
   * @brief 交易所发送给交易客户端的订单响应类型
   * 
   * @details 定义了交易所可以发送给交易客户端的不同类型的响应，
   * 包括订单接受、取消、成交和取消被拒绝等状态。
   */
  enum class ClientResponseType : uint8_t {
    INVALID = 0,         ///< 无效响应类型
    ACCEPTED = 1,        ///< 订单已被接受
    CANCELED = 2,        ///< 订单已被取消
    FILLED = 3,          ///< 订单已成交
    CANCEL_REJECTED = 4  ///< 取消订单请求被拒绝
  };

  /**
   * @brief 将客户端响应类型转换为字符串表示
   * 
   * @details 该函数将ClientResponseType枚举值转换为其对应的字符串表示，
   * 主要用于日志记录和调试输出。
   * 
   * @param type 要转换的客户端响应类型
   * @return std::string 客户端响应类型的字符串表示
   */
  inline std::string clientResponseTypeToString(ClientResponseType type) {
    switch (type) {
      case ClientResponseType::ACCEPTED:
        return "ACCEPTED";
      case ClientResponseType::CANCELED:
        return "CANCELED";
      case ClientResponseType::FILLED:
        return "FILLED";
      case ClientResponseType::CANCEL_REJECTED:
        return "CANCEL_REJECTED";
      case ClientResponseType::INVALID:
        return "INVALID";
    }
    return "UNKNOWN"; // 处理未定义的枚举值
  }

  /**
   * @brief 二进制结构打包指令
   * 
   * @details 这些结构会通过网络传输，因此使用打包指令移除系统相关的额外填充，
   * 确保不同系统之间的二进制兼容性。
   */
#pragma pack(push, 1)

  /**
   * @brief 匹配引擎内部使用的客户端响应结构
   * 
   * @details 该结构定义了匹配引擎内部处理的客户端响应格式，
   * 包含响应类型、客户端ID、证券ID、订单ID、交易方向、价格和数量等信息。
   * 这些信息用于向客户端反馈订单处理的状态和结果。
   */
  struct MEClientResponse {
    /**
     * @brief 客户端响应类型
     * 
     * @details 指定该响应的类型，如订单已接受、已取消、已成交等
     */
    ClientResponseType type_ = ClientResponseType::INVALID;
    
    ClientId client_id_ = ClientId_INVALID;         ///< 客户端ID，用于标识响应的目标客户端
    TickerId ticker_id_ = TickerId_INVALID;         ///< 证券ID，指定订单相关的证券
    OrderId client_order_id_ = OrderId_INVALID;     ///< 客户端订单ID，客户端用于跟踪订单的标识符
    OrderId market_order_id_ = OrderId_INVALID;     ///< 市场订单ID，交易所内部用于跟踪订单的标识符
    Side side_ = Side::INVALID;                     ///< 交易方向，买入或卖出
    Price price_ = Price_INVALID;                  ///< 订单价格
    Qty exec_qty_ = Qty_INVALID;                   ///< 执行数量，已成交的数量
    Qty leaves_qty_ = Qty_INVALID;                 ///< 剩余数量，还未成交的数量

    /**
     * @brief 将客户端响应转换为字符串表示
     * 
     * @details 该方法将MEClientResponse结构的内容格式化为便于阅读的字符串，
     * 主要用于日志记录和调试输出。字符串包含响应类型、客户端ID、
     * 证券ID、订单ID、交易方向、成交数量、剩余数量和价格等信息。
     * 
     * @return std::string 响应的字符串表示
     */
    auto toString() const {
      std::stringstream ss;
      ss << "MEClientResponse"
         << " ["
         << "type:" << clientResponseTypeToString(type_)    // 响应类型
         << " client:" << clientIdToString(client_id_)     // 客户端ID
         << " ticker:" << tickerIdToString(ticker_id_)     // 证券ID
         << " coid:" << orderIdToString(client_order_id_)  // 客户端订单ID
         << " moid:" << orderIdToString(market_order_id_)  // 市场订单ID
         << " side:" << sideToString(side_)                // 交易方向
         << " exec_qty:" << qtyToString(exec_qty_)         // 执行数量
         << " leaves_qty:" << qtyToString(leaves_qty_)     // 剩余数量
         << " price:" << priceToString(price_)             // 价格
         << "]";
      return ss.str();
    }
  };

  /**
   * @brief 订单服务器通过网络发布的客户端响应结构
   * 
   * @details 该结构定义了订单服务器通过网络发送给客户端的响应格式。
   * 它包含一个序列号和一个匹配引擎客户端响应结构。序列号用于确保消息的可靠传输
   * 和按序处理，帮助客户端检测消息丢失或乱序的情况。
   */
  struct OMClientResponse {
    size_t seq_num_ = 0;                      ///< 序列号，用于确保消息的可靠传输和按序处理
    MEClientResponse me_client_response_;     ///< 匹配引擎客户端响应结构，包含响应的具体信息

    /**
     * @brief 将订单服务器客户端响应转换为字符串表示
     * 
     * @details 该方法将OMClientResponse结构的内容格式化为便于阅读的字符串，
     * 主要用于日志记录和调试输出。字符串包含序列号和内部MEClientResponse结构的字符串表示。
     * 
     * @return std::string 响应的字符串表示
     */
    auto toString() const {
      std::stringstream ss;
      ss << "OMClientResponse"
         << " ["
         << "seq:" << seq_num_                       // 序列号
         << " " << me_client_response_.toString()    // 内部客户端响应结构
         << "]";
      return ss.str();
    }
  };

/**
   * @brief 取消二进制结构打包指令
   * 
   * @details 恢复默认的结构对齐方式，取消前面的打包指令对后续代码的影响。
   */
#pragma pack(pop) // Undo the packed binary structure directive moving forward.

  /**
   * @brief 匹配引擎客户端订单响应消息的无锁队列
   * 
   * @details 定义了一个存储MEClientResponse对象的无锁队列类型。
   * 该队列用于匹配引擎和订单服务器之间的通信，实现了高效的线程间数据传输。
   * 无锁队列确保了在多线程环境下的线程安全性，无需使用互斥锁或其他同步原语。
   */
  typedef LFQueue<MEClientResponse> ClientResponseLFQueue;
}
